package cn.edu.sjtu.tooling.service.impl;

import cn.edu.sjtu.tooling.domain.Task;
import cn.edu.sjtu.tooling.dto.StateDTO;
import cn.edu.sjtu.tooling.dto.TaskDTO;
import cn.edu.sjtu.tooling.enums.ECNStateEnum;
import cn.edu.sjtu.tooling.enums.TaskStateEnum;
import cn.edu.sjtu.tooling.service.ToolingService;
import cn.edu.sjtu.tooling.util.TaskExecuteUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ToolingMockServiceImpl implements ToolingService {

  private Queue<Task> taskQueue = new LinkedBlockingQueue<>();

  private final TaskExecuteUtil taskExecuteUtil;

  public ToolingMockServiceImpl(TaskExecuteUtil taskExecuteUtil) {
    this.taskExecuteUtil = taskExecuteUtil;
  }

  @Override
  public StateDTO queryECNState() {
    return StateDTO.ofECNState(taskExecuteUtil.getDeviceStatus());
  }

  @Override
  public Map<Integer, List<Task>> retTasksPool() {
    return taskExecuteUtil.getTaskPool().values().stream()
        .collect(
            Collectors.groupingBy(
                item -> item.getStatus().ordinal(), LinkedHashMap::new, Collectors.toList()));
  }

  @Override
  public boolean addTaskToQueue(TaskDTO taskDTO) {
    Task task = new Task();
    BeanUtils.copyProperties(taskDTO, task);
    task.setStatus(TaskStateEnum.PENDING);
    task.setReleaseTime(new Date());
    String key = task.getProcessId().concat(task.getTaskId());
    taskExecuteUtil.getTaskPool().put(key, task);
    return taskQueue.offer(task);
  }

  @Override
  public StateDTO queryTaskState(String processId, String taskId) {
    String key = processId.concat(taskId);
    Map<String, Task> taskMap = taskExecuteUtil.getTaskPool();
    Task task = taskMap.get(key);
    if (task != null) {
      StateDTO stateResponse = StateDTO.ofTaskState(task);
      if (task.getStatus() == TaskStateEnum.PENDING) {
        return StateDTO.ofTaskPendingState();
      } else if (task.getStatus() == TaskStateEnum.DONE) {
        //        taskMap.remove(key);
      }
      return stateResponse;
    }
    return null;
  }

  @Scheduled(fixedRate = 2000)
  public void executeTask() {
    // ready 才 poll , busy 不 poll
    if (!taskQueue.isEmpty() && taskExecuteUtil.getDeviceStatus() == ECNStateEnum.READY) {
      Task task = taskQueue.poll();
      taskExecuteUtil.executeTask(task);
    }
    Task currentTask = taskExecuteUtil.getCurrentTask();
    if (currentTask != null) {
      log.info("当前执行的任务为: {}, 状态是: {}", currentTask.getTaskId(), taskExecuteUtil.getDeviceStatus());
    }
    log.info(
        "已执行队列为: {}, 当前任务:{},  当前状态{}",
        taskExecuteUtil.getTaskPool(),
        currentTask,
        taskExecuteUtil.getDeviceStatus());
  }
}
